import asyncio
import base64
import hashlib
import json
import logging
import urllib

import aioredis
import tornado
from tornado import gen

from baseHandler import http_result, Application, PayHandler, init_logger
from channel.minsheng import MinSheng
from util import aes
from channel.weixinback import  Weixin, parse_xml, check_sign, create_xml

logger = init_logger("app", "/app/log/app/app.log")

class MainHandler(tornado.web.RequestHandler):
    @gen.coroutine
    def get(self):
        print('start')

        self.write('hello world')

    def post(self):
        logger.debug(self.request.arguments)
        logger.debug(self.request.body)
        self.merchantid = self.get_argument('data')
        logger.info(self.merchantid)

class RBWalletHandler(PayHandler):
    @gen.coroutine
    def post(self, method):
        print(self.get_argument('merchantid'))
        if method == 'account_balance':
            channel = 'http://127.0.0.1:10000/rongbang/account_balance'
        elif method == 'batch_transfer':
            channel = 'http://127.0.0.1:10000/rongbang/batch_transfer'
        yield self.merchant_exit()
        if not self.check_sign():
            return self.write(json.dumps({"message": "签名验证失败"}))
        data = self.decrypt()

        response = yield http_result(channel, data)
        logger.info(response.body.decode('utf-8'))
        self.write(response.body)


class TestNoitfy(PayHandler):
    def post(self):
        logger.debug(self.request.arguments)
        sign = self.get_argument("sign")
        merchantid = self.get_argument("merchantid")
        timestamp = self.get_argument("timestamp")
        data = self.get_argument("data")
        sign_string = "1234567890123456" + merchantid + data + timestamp + "1234567890123456"
        check_sign = hashlib.sha256(sign_string.encode("utf-8")).hexdigest()
        logger.debug('sign %s == %s', check_sign, sign)
        if check_sign != sign:
            logger.debug("验证识别")
        self.aes_key = '6543210987654321'
        data = self.decrypt()
        logger.debug(data)
        logger.debug(self.request.body)
        self.write("success")


class NotifyHandler(PayHandler):
    def get(self):
        logger.debug(self.request.arguments)
        self.write(json.dumps({"response": "00", "message": "处理成功"}))

    @gen.coroutine
    def post(self):
        logger.info(self.request.arguments)
        logger.info(self.request.body)
        # 解析异步通知结果
        data = self.get_argument('Data')
        logger.debug(self.request.arguments)
        data = base64.urlsafe_b64decode(data)
        # channel = rongbang.RongBang()

        # 获取渠道信息
        redis_1 = self.application.redis_1
        rb_appid = self.get_argument('Appid')
        channel_info  =  yield from redis_1.hget('rongbang', rb_appid)
        channel_info = json.loads(channel_info.decode('utf-8'))
        crypto = aes.AesEncryption(channel_info['secretkey'])

        data = crypto.decrypt(data)
        logger.debug(json.loads(data))
        data = json.loads(data)
        if data["respcode"] == 1:
            respcode = "8"
        elif data["respcode"] == 2:
            respcode = "0"
        elif data["respcode"] == 3 or data["respcode"] == 4:
            respcode = "1"

        self.write(json.dumps({"response": "00", "message": "处理成功"}))
        self.finish()
        logger.info("通知|流水号%s|支付结果%s", data["ordernumber"], respcode)
        input_json = {
            "DEPTID": "800001",
            "OPERID": "9527",
            "FUNCTYPE": "NOTI",
            "FUNCCODE": "100201",
            "OPERPASS": "f15dbcb3154d37e4a183a350e4e8a15dde16a175",
            "REQINFO": {
                'OUTERORDERNO': data["ordernumber"],
                "ORDERSTATE": respcode,
                "OPMONEY": str(data["amount"]),
                "NOTIFYINFO": data['payorderid'],
            }

        }
        # 发送到核心程序
        result = yield from self.pay_core("PAY_ALIPAY_NOTIFY", input_json)
        logger.info(result)
        notifyurl = result.get("NOTIFIYURL", "")

        if notifyurl:
            merchantid = result.get("MERCHANTID")
            res = yield self.merchant_exit(merchantid=merchantid)
            for i in range(5):
                notify_data = {
                    "ordernumber": result["MERCHANTORDERNO"],
                    "respcode": result["ORDERSTATE"],
                    "merchantid": merchantid,
                    "amount": result["OPMONEY"],
                    "businesstime": result["RESPTIME"]
                }

                request_obj = self.niti_data(notify_data, result)
                rsp = yield http_result(notifyurl, request_obj, model='urlencode')
                logger.info(rsp.body)
                # content = rsp.body.upper()
                if rsp.code == 200 and rsp.body in (b'SUCCESS', b'success'):
                    logger.info("%s|%s收到下游成功应答|订单号%s", i, data["ordernumber"], result["MERCHANTORDERNO"])
                    noti = yield from self.pay_core("PAY_ALIPAY_NOTIFY_RES", {
                        "REQINFO": {"MERCHANTID": merchantid, "MERCHANTORDERNO": result["MERCHANTORDERNO"]}})
                    logger.debug(noti)
                    break
                else:
                    logger.info("%s|%s未收到下游成功应答|订单号%s", i, data["ordernumber"], result["MERCHANTORDERNO"])
                    yield from asyncio.sleep(10*(i+1))


class MinShengNotify(PayHandler):
    def get(self):
        logger.info(self.request.arguments)
        self.write('SUCCESS')

    @gen.coroutine
    def post(self):
        logger.info(self.request.arguments)
        arguments = self.request.arguments
        merNo = self.get_argument("merNo")
        channel_info = yield from self.application.redis_1.hget('minsheng', merNo)
        channel_info = json.loads(channel_info.decode('utf-8'))
        prv = channel_info['prv']
        pub = channel_info['pub']
        ms = MinSheng(merNo, prv, pub)
        logger.info(prv)
        logger.info(pub)

        content, signature = ms.parse_body(self.request.body)

        if not ms.rsa_verify(content, signature):
            return self.write("")

        ordernumber = self.get_argument('orderNo')
        amount = self.get_argument("transAmt")
        respcode = self.get_argument('respCode')
        if respcode == "0000":
            orderstate = 0
        else:
            orderstate = 1
        input_json = {
            "DEPTID": "800001",
            "OPERID": "9527",
            "FUNCTYPE": "NOTI",
            "FUNCCODE": "100201",
            "OPERPASS": "f15dbcb3154d37e4a183a350e4e8a15dde16a175",
            "REQINFO": {
                'OUTERORDERNO': ordernumber,
                "ORDERSTATE": orderstate,
                "OPMONEY": amount,
                # "NOTIFYINFO": data['payorderid'],
            }
        }
        result = yield from self.pay_core("PAY_ENTRUST_NOTIFY", input_json)
        logger.debug(result)
        notifyurl = result.get("NOTIFIYURL", "")
        merchantid = result.get("MERCHANTID")
        res = yield self.merchant_exit(merchantid=merchantid)
        if notifyurl:
            for i in range(5):
                notify_data = {
                    "ordernumber": result["MERCHANTORDERNO"],
                    "respcode": result["ORDERSTATE"],
                    "merchantid": merchantid,
                    "amount": result["OPMONEY"],
                    "businesstime": result["RESPTIME"]
                }

                request_obj = self.niti_data(notify_data, result)
                rsp = yield http_result(notifyurl, request_obj, model='urlencodeex')
                content = rsp.body.decode('utf-8').upper()
                if rsp.code == 200 and content == 'SUCCESS':
                    logger.info("%s 通知收到成功应答 订单号 %s ", i, result["MERCHANTORDERNO"])
                    noti = yield from self.pay_core("PAY_ENTRUST_NOTIFY_RES", {
                        "REQINFO": {"MERCHANTID": merchantid, "MERCHANTORDERNO": result["MERCHANTORDERNO"]}})
                    logger.debug(noti)
                    break
                else:
                    logger.info("%s 通知未收到成功应答 订单号 %s ", i, result["MERCHANTORDERNO"])
                    yield from asyncio.sleep(10)

        self.write(json.dumps({"response": "00", "message": "处理成功"}))



class WeiXinNotify(PayHandler):
    def get(self):
        logger.info(self.request.arguments)
        self.write('SUCCESS')

    @gen.coroutine
    def post(self):
        logger.info(self.request.body)
        appid = 'wxbfc12fe727de1533'
        mch_id = '1447172802'
        # key = 'FC1528682BC23018AAE7B0DB37994512'
        key = 'ruTPBXISkruDGNJFtJuihegQZRLKWIIi'
        channel = Weixin(appid, mch_id, None, key)
        result = parse_xml(self.request.body.decode('utf-8'))

        if result['return_code'] == 'SUCCESS' and result['result_code'] == 'SUCCESS':
            if not check_sign(result, channel.key):
                logger.warn("签名校验失败")
                return self.write(json.dumps(result))
            respcode = {'SUCCESS':'0', 'FAIL': '1'}[result['result_code']]
        else:
            return self.write(create_xml({"return_code": "FAIL", "return_msg": "签名校验失败"}))

        input_json = {
            "DEPTID": "800001",
            "OPERID": "9527",
            "FUNCTYPE": "NOTI",
            "FUNCCODE": "100201",
            "OPERPASS": "f15dbcb3154d37e4a183a350e4e8a15dde16a175",
            "REQINFO": {
                'OUTERORDERNO': result["out_trade_no"],
                "ORDERSTATE": respcode,
                "OPMONEY": str(result["total_fee"]),
                "NOTIFYINFO": result['transaction_id'],
            }

        }
        # 发送到核心程序
        self.write(create_xml({"return_code": "SUCCESS", "return_msg": "OK"}))
        result = yield from self.pay_core("PAY_WEIXIN_NOTIFY", input_json)
        logger.debug(result)
        notifyurl = result.get("NOTIFIYURL", "")
        merchantid = result.get("MERCHANTID")
        res = yield self.merchant_exit(merchantid=merchantid)
        if notifyurl:
            for i in range(5):
                notify_data = {
                    "ordernumber": result["MERCHANTORDERNO"],
                    "respcode": result["ORDERSTATE"],
                    "merchantid": merchantid,
                    "amount": result["OPMONEY"],
                    "businesstime": result["RESPTIME"]
                }

                request_obj = self.niti_data(notify_data, result)
                rsp = yield http_result(notifyurl, request_obj, model='urlencode')
                content = rsp.body.decode('utf-8').upper()
                if rsp.code == 200 and content == 'SUCCESS':
                    logger.info("%s 通知收到成功应答 订单号 %s ", i, result["MERCHANTORDERNO"])
                    noti = yield from self.pay_core("PAY_ALIPAY_NOTIFY_RES", {
                        "REQINFO": {"MERCHANTID": merchantid, "MERCHANTORDERNO": result["MERCHANTORDERNO"]}})
                    logger.debug(noti)
                    break
                else:
                    logger.info("%s 通知未收到成功应答 订单号 %s ", i, result["MERCHANTORDERNO"])
                    yield from asyncio.sleep(10)



if __name__ == "__main__":
    handlers = [
        (r'/rb/wallet/(\w+)', RBWalletHandler),
        (r"/rbgznotify/?", NotifyHandler),  # http://notify.3035pay.com/rbgznotify
        (r'/msgznotify/?', MinShengNotify),
        (r'/testnotify/?', TestNoitfy),
        (r'/wxnotify/?', WeiXinNotify ),
    ]

    logger.info("Run base server ... http://127.0.0.1:9999")
    application = Application(handlers)
    application.listen(9999, address="127.0.0.1")

    loop = asyncio.get_event_loop()
    redis_1 = loop.run_until_complete(
        aioredis.create_redis(('localhost', 12580), password='PayCore#8bill',db=1, loop=loop)
    )
    application.redis_1 = redis_1
    application.init_with_loop(loop)
    loop.run_forever()